#ifndef _REACTOR_HPP
#define _REACTOR_HPP

#include "Task.hpp"

/*
 * 实现ET工作方式的epoll模型(非阻塞)
 * Rector封装
 * LT(阻塞和非阻塞都可以)
*/

class Event;
class Reactor;

class Reactor
{
public:
    const int NUM = 1024;
    const int SIZE = 1024;
    int _epfd;
    // 可以不需要，因为epoll_event中有字段data里的ptr，可以回指Event
    std::unordered_map<int, Event*> _events_map;

    Reactor()
      :_epfd(-1)
    {}

    bool InitReactor()
    {
        _epfd = epoll_create(SIZE);
        if(_epfd == -1)
        {
            fprintf(stdout, "epoll_create: %s\n", strerror(errno));
            return false;
        }
      
        fprintf(stdout, "Initializing reactor succed!\n");
        return true;
    }

    bool InsertEvent(Event* event, uint32_t cmd)
    {
        if(_epfd == -1)
        {
            fprintf(stderr, "uninitializing Reactor!\n");
            return false;
        }

        // 构造ev，插入对应的Event中
        struct epoll_event ev;
        ev.events = cmd;
        ev.data.fd = event->_sock;
        event->_event = ev;
        if(epoll_ctl(_epfd, EPOLL_CTL_ADD, event->_sock, &ev) == -1)
        {
            fprintf(stderr, "epoll_ctl: %s\n", strerror(errno));
            return false;
        }

        _events_map.insert({event->_sock, event});
        fprintf(stdout, "InserEvent succeed!\n");
        return true;
    }

    void _Dispatch(struct epoll_event* revents, int n)
    {
        assert(revents); 
        for(int i = 0; i < n; ++i)
        {
            Task t;
            t(_events_map[revent[i].fd]);
            tp->PushTask(t);
        }
    }

    // 事件派发器
    void Dispatcher(int timeout)
    {
        struct epoll_event revents[NUM];
        int n = epoll_wait(_epfd, revents, NUM, timeout);
        switch(n)
        {
            case -1:
              fprintf(stderr, "epoll_wait: %s\n", strerror(errno));
              break;
            case 0:
              fprintf(stdout, "timeout!\n");
              break;
            default:
              _Dispatch(revents, n);
        }

        
    }

    bool EnableAbility(int fd, bool read_ability, bool write_ability)
    {
        struct epoll_event ev;
        ev.events = (read_ability? EPOLLIN : 0) | (write_ability? EPOLLOUT : 0);
        ev.data.fd = fd;
        if(epoll_ctl(_epfd, EPOLL_CTL_MOD, fd, &ev) == -1)
        {
            fprintf(stderr, "epoll_ctl: %s\n", strerror(errno));
            return false;
        }

        return true;
    }

    void DeleteEvent(Event* delete_event)
    {
        std::unordered_map<int, Event*>::iterator it = _events_map.find(delete_event->_sock);
        if(it != _events_map.end())
        {
            fprintf(stdout, "fd not exits!\n");
            return;
        }

        // 从映射中删除
        _events_map.erase(it);
        // 从epoll中删除
        if(epoll_ctl(_epfd, EPOLL_CTL_DEL, delete_event->_sock, &delete_event->_event) == -1)
        {
            fprintf(stderr, "epoll_ctl: %s\n", strerror(errno));
            return;
        }
        // 关闭文件描述符
        close(delete_event->_sock);
        // 释放内存
        delete delete_event;
        delete_event = nullptr;
        fprintf(stdout, "Delete succed!\n");
    }

    ~Reactor()
    {
        _epfd = -1;
    }
};


#endif
